from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


class FormHelper:
    def __init__(self, driver):
        """初始化工具类

        参数:
            driver: Selenium WebDriver 实例
        """
        self.driver = driver

    def clear_fields(self, css_selectors):
        """清空一组输入框内容

        参数:
            css_selectors: 需要清空的输入框 CSS 选择器列表
        """
        for selector in css_selectors:
            self.driver.find_element(By.CSS_SELECTOR, selector).clear()

    def  fill_fields(self, values_by_selector):
        """按选择器填充对应的文本值

        参数:
            values_by_selector: dict，key 为 CSS 选择器，value 为要输入的文本
        """
        for selector, value in values_by_selector.items():
            # 新增: 先等待元素出现再填充
            WebDriverWait(self.driver, 5).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, selector))
            )
            self.driver.find_element(By.CSS_SELECTOR, selector).send_keys(value)

    def click(self, css_selector):
        """点击指定元素

        参数:
            css_selector: 需要点击元素的 CSS 选择器
        """
        WebDriverWait(self.driver, 5).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, css_selector))
        )
        self.driver.find_element(By.CSS_SELECTOR, css_selector).click()

    def verify_error_message(self, css_selector, expected_text, timeout=10):
        """校验错误提示文本是否与预期一致

        参数:
            css_selector: 错误信息元素的 CSS 选择器
            expected_text: 期望的错误提示文本
            timeout: 等待元素可见的超时时间（秒）

        抛出:
            AssertionError: 当实际文本与期望不一致时
        """
        error_element = WebDriverWait(self.driver, timeout).until(
            EC.visibility_of_element_located((By.CSS_SELECTOR, css_selector))
        )
        actual_text = error_element.text.strip()
        print(actual_text)
        assert actual_text == expected_text

    #在规定时间找到元素是否存在
    def is_element_present(self, css_selector, timeout=0):
        """判断元素是否存在

        参数:
            css_selector: 目标元素的 CSS 选择器
            timeout: 可选，>0 时在限定时间内轮询等待元素出现（秒）

        返回:
            bool: 存在返回 True，否则 False
        """
        try:
            if timeout and timeout > 0:
                WebDriverWait(self.driver, timeout).until(
                    EC.presence_of_element_located((By.CSS_SELECTOR, css_selector))
                )
                return True
            else:
                self.driver.find_element(By.CSS_SELECTOR, css_selector)
                return True
        except Exception:
            return False

    # 支持列表，检查列表中的所有元素是否存在
    def are_all_elements_present(self, css_selectors, timeout=0):
        """检查一组元素是否全部存在

        参数:
            css_selectors: 需要检查的 CSS 选择器列表/集合
            timeout: 可选，>0 时对每个元素应用等待（秒）

        返回:
            bool: 全部存在返回 True，否则 False
        """
        for selector in css_selectors:
            if not self.is_element_present(selector, timeout):
                return False
        return True

    def wait_for_presence(self, css_selector, timeout=10):
        """等待元素出现在 DOM 中（可不可见均可）

        参数:
            css_selector: 目标元素的 CSS 选择器
            timeout: 等待超时时间（秒）

        返回:
            bool: 元素在超时前出现返回 True，否则 False
        """
        try:
            WebDriverWait(self.driver, timeout).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, css_selector))
            )
            return True
        except Exception:
            return False

    def wait_for_visibility(self, css_selector, timeout=10):
        """等待元素可见

        参数:
            css_selector: 目标元素的 CSS 选择器
            timeout: 等待超时时间（秒）

        返回:
            bool: 元素在超时前可见返回 True，否则 False
        """
        try:
            WebDriverWait(self.driver, timeout).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, css_selector))
            )
            return True
        except Exception:
            return False

    def screenshot_after_presence(self, css_selector, timeout=10, extra_delay=2):
        """等待元素出现后再截图，统一避免截图过早

        参数:
            css_selector: 用于判断页面已加载完成的关键元素 CSS 选择器
            timeout: 等待超时时间（秒）
            extra_delay: 元素出现后的额外等待时间（秒），确保页面完全渲染

        返回:
            bool: 截图是否成功触发（等待成功才截图）
        """
        try:
            # 等待元素出现
            WebDriverWait(self.driver, timeout).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, css_selector))
            )
            
            # 额外等待确保页面完全渲染
            import time
            time.sleep(extra_delay)
            
            # 等待页面加载完成（通过检查document.readyState）
            WebDriverWait(self.driver, 5).until(
                lambda driver: driver.execute_script("return document.readyState") == "complete"
            )
            
            # 再次短暂等待确保所有异步内容加载完成
            time.sleep(1)
            
            from Common.Utils import blog_driver
            blog_driver.GetScreeShot()
            return True
        except Exception:
            return False

    def auto_login(self, url, login_func=None, login_url_kw="login", home_url_kw="home", timeout=20):
        """
        通用自动登录方法：用于先尝试访问url，如果已登录直接进入首页，否则执行指定登录逻辑

        参数：
            url: 登录后要进入的主页url，如 'http://49.235.61.184:8080/home'
            login_func: 未登录时调用的登录逻辑（传入一个无参数的函数/方法，如 Login().LoginSuTest），可为None
            login_url_kw: 登录页URL关键字，用于识别重定向到登录页（默认"login"）
            home_url_kw: 主页URL关键字，用于识别已经在主页（默认"home"）
            timeout: 等待URL跳转的秒数（默认10）
        """
        self.driver.get(url)
        WebDriverWait(self.driver, timeout).until(
            lambda d: login_url_kw in d.current_url or home_url_kw in d.current_url
        )
        if login_url_kw in self.driver.current_url:
            if login_func:
                login_func()
                # 登录后重定向到主页
                WebDriverWait(self.driver, timeout).until(lambda d: home_url_kw in d.current_url)




